package owg.util.editor2d.operations;

import owg.util.data.Pair;
import owg.util.data.KryoInstance.K;
import owg.util.editor2d.ConstructorParams;
import owg.util.editor2d.Editor2D;
import owg.util.editor2d.entity.Placeable2D;

public class Unconstructor extends Operation
{
	final ConstructorInvoker source;
	@K private Unconstructor() {source = null;}
	/**Create an inverse constructor invoker with respect to the given companion.*/
	public Unconstructor(ConstructorInvoker source)
	{
		this.source = source;
	}
	
	@Override
	public void apply(Editor2D w)
	{
		Pair<Placeable2D, ConstructorParams> target = source.getCreatedObject(true);
		w.objectUncreated(target);
		target.a.destroy();
	}
}
//	
//	public static class MultiConstructorInvoker extends Operation
//		{
//		final ConstructorInvoker[] children;
//		final TransformationData[] transformations;
//		final VisualData[] visualOps;
//		final Enum<?>[][] customParams;
//		final Object[][] customValues;
//
//		public MultiConstructorInvoker(ConstructorInvoker op, TransformationData transOp, VisualData visualOp, Enum<?>[] customParams, Object[] customValues)
//			{
//			this(
//					new ConstructorInvoker[] {op},
//					new TransformationData[] {transOp}, 
//					new VisualData[] {visualOp}, 
//					new Enum<?>[][] {customParams}, 
//					new Object[][] {customValues}
//					);
//			}
//		
//		public MultiConstructorInvoker(ConstructorInvoker[] children, TransformationData[] transformations, 
//									   VisualData[] visualOps, Enum<?>[][] customParams, Object[][] customValues)
//			{
//			this.children = children;
//			this.transformations = transformations;
//			this.visualOps = visualOps;
//			this.customParams = customParams;
//			this.customValues = customValues;
//			}
//
//		@Override
//		public void apply(Editor2D w)
//			{
//			try
//				{
//				int startIndex = w.getSelectableObjects().size();
//				for(ConstructorInvoker c : children)
//					c.apply(w);
//				for(TransformationData t : transformations)
//					t.apply(w);
//				for(VisualData t : visualOps)
//					t.apply(w);
//				
//				ArrayList<Pair<Placeable2D, ConstructorParams>> ps = w.getSelectableObjects();
//				
//				for(int i = 0; i<customParams.length; i++)
//					{
//					if(customParams[i] != null)
//						{
//						Placeable2D pp = ps.get(transformations[i].objectIndex).a;
//						if(!(pp instanceof Customizable))
//							{
//							System.out.println(getClass().getSimpleName()+" cannot apply custom parameters to "+pp+", continuing.");
//							continue;
//							}
//						Customizable p = (Customizable)pp;
//						
//						Enum<?>[] realParams = p.getParameterNames();
//						if (Arrays.equals(realParams, customParams[i]))
//							{
//							for(int j = 0; j<customParams[i].length; j++)
//								{
//								//Avoid triggering customizable buttons since this is just not necessary
//								if(!(customValues[i][j] instanceof NullTuple))
//									{
//									p.setParameterValue(customParams[i][j], customValues[i][j]);
//									}
//								}
//							}
//						else
//							{
//							int mismatches = 0;
//							System.out.println(getClass().getSimpleName()+" trying to apply parameters to "+p+" with different custom parameters...");
//							for(int j = 0; j<customParams[i].length; j++)
//								{
//								//Need to search for a compatible parameter with the same name...
//								//Avoid triggering customizable buttons since this is just not necessary
//								Enum<?> pName = customParams[i][j];
//								Object pValue = customValues[i][j];
//								if(!(pValue instanceof NullTuple))
//									{
//									Enum<?> pMatch = null;
//									boolean typeMismatch = false;
//									matchSearch:
//									for(int k = 0; k<realParams.length; k++)
//										{
//										Enum<?> pCand = realParams[k];
//										if(pCand.toString().equals(pName.toString()))
//											{
//											if(p.getParameterValue(pCand).getClass().isAssignableFrom(pValue.getClass()))
//												pMatch = pCand;
//											else
//												{
//												System.out.println("Name match for "+pCand+" but incompatible types "+
//															pValue.getClass().getSimpleName()+"->"+
//															p.getParameterValue(pCand).getClass().getSimpleName());
//												typeMismatch = true;
//												}
//											break matchSearch;
//											}
//										}
//									if(pMatch != null)
//										p.setParameterValue(pMatch, pValue);
//									else
//										{
//										if(!typeMismatch)
//											System.out.println("No name match for parameter: "+pName);
//										mismatches++;
//										}
//									}
//								}
//							System.out.println("Reported "+mismatches+"/"+customParams[i].length+" custom parameter mismatches.");
//							}
//						}
//					}
//				w.setSelectedIndices(Calc.getCountingSet(startIndex, startIndex+children.length), false, false);
//				}
//			catch (OperationFailedException e)
//				{
//				System.out.println("Unexpected error: ");
//				e.printStackTrace();
//				}
//			}
//		}
//	
//	public static class InverseMultiConstructorInvoker extends Operation
//		{
//		final InverseConstructorInvoker[] children;
//
//		public InverseMultiConstructorInvoker(InverseConstructorInvoker child)
//			{
//			this(new InverseConstructorInvoker[]{child});
//			}
//		public InverseMultiConstructorInvoker(InverseConstructorInvoker[] children)
//			{
//			this.children = children;
//			}
//		
//		@Override
//		public void apply(Editor2D w)
//			{
//			for(InverseConstructorInvoker c : children)
//				c.apply(w);
//			}
//		}
//	
//	public static class Transformation extends Operation
//		{
//		/**Backwards compatible*/
//		public static class TDO
//			{
//			public Float xScale, yScale, zScale;
//			public V3D pos;
//			public String name;
//			public Double rotation;
//			public V3D x,y,z;
//			public int objectIndex;
//			public byte mask;
//			}
//		
//		public static class TransformationData implements Serializable
//			{
//			private static final long serialVersionUID = -4642068711888928889L;
//			
//			public boolean makeNameUnique;
//			
//			public final Float xScale, yScale, zScale;
//			public final V3D pos;
//			
//			public final Integer depth;
//			public final MotionAxis motionAxis;
//			public final String name;
//			public final Double rotation;
//			public final V3D x,y,z;
//			
//			public int objectIndex;
//			public final byte mask;
//
//			
//			/**Only used by Kryo*/
//			@SuppressWarnings("unused")
//			private TransformationData()
//				{depth=null;name=null;xScale=null;yScale=null;zScale=null;pos=null;rotation=null;
//				x=null;y=null;z=null;objectIndex=0;mask=0;makeNameUnique=false;motionAxis=null;}
//			
//			public TransformationData(TDO s) 
//				{
//				makeNameUnique = false;
//				xScale = s.xScale;
//				yScale = s.yScale;
//				zScale = s.zScale;
//				pos = s.pos;
//				name = s.name;
//				depth = null;
//				motionAxis = null;
//				rotation = s.rotation;
//				x = s.x;
//				y = s.y;
//				z = s.z;
//				objectIndex = s.objectIndex;
//				mask = s.mask;
//				}
//			public TransformationData(int index, TransformationData source)
//				{
//				this.objectIndex = index;
//				mask = source.mask;
//				xScale = source.xScale;
//				yScale = source.yScale;
//				zScale = source.zScale;
//				pos = source.pos;
//				name = source.name;
//				depth = source.depth;
//				motionAxis = source.motionAxis;
//				rotation = source.rotation;
//				x = source.x;
//				y = source.y;
//				z = source.z;
//				makeNameUnique = source.makeNameUnique;
//				}
//			
//			public void offset(int offset)
//				{
//				objectIndex += offset;
//				}
//
//			public TransformationData(int selected, Placeable2D objects, byte mask, boolean generateUniqueName)
//				{
//				this.makeNameUnique = generateUniqueName;
//				this.objectIndex = selected;
//				this.mask = mask;
//				
//				if((mask&Placeable2D.CHANGE_METADATA) != 0)
//				{
//					name = objects.getName();
//					if(objects instanceof RegisteredTerrain.MovableTerrain)
//						motionAxis = ((RegisteredTerrain.MovableTerrain)objects).getMotionAxis();
//					else
//						motionAxis = null;
//					if(objects instanceof Placeable2D.DepthPlaceable2D)
//						depth = ((Placeable2D.DepthPlaceable2D)objects).getDepth();
//					else
//						depth = null;
//				}
//				else
//				{
//					name = null;
//					motionAxis = null;
//					depth = null;
//				}
//				if((mask&Placeable2D.CHANGE_POSITION) > 0)
//					pos = objects.getPosition().clone();
//				else
//					pos = null;
//				if(objects instanceof Scaleable && (mask&Placeable2D.CHANGE_SCALE) > 0)
//					{
//					xScale = ((Scaleable) objects).getXScale();
//					yScale = ((Scaleable) objects).getYScale();
//					zScale = ((Scaleable) objects).getZScale();
//					}
//				else
//					{
//					xScale = null;
//					yScale = null;
//					zScale = null;
//					}
//				if(objects instanceof FixedRotateable && (mask&Placeable2D.CHANGE_ROTATION) > 0)
//					rotation = ((FixedRotateable) objects).getRotation();
//				else
//					rotation = null;
//				if(objects instanceof FreeRotateable && (mask&Placeable2D.CHANGE_ROTATION) > 0)
//					{
//					x = ((FreeRotateable) objects).getXVector().clone();
//					y = ((FreeRotateable) objects).getYVector().clone();
//					z = ((FreeRotateable) objects).getZVector().clone();
//					}
//				else
//					{
//					x = null;
//					y = null;
//					z = null;
//					}
//				objects.transformationChanged(mask);
//				}
//			public void apply(Editor2D w) throws OperationFailedException
//				{
//				Placeable2D p = w.getSelectableObjects().get(objectIndex).a;
//				
//				if(getGenerateUniqueName())
//					p.setName(w.getUniqueName(p, name));
//				else if(name != null)
//					p.setName(name);
//				if(motionAxis != null && p instanceof RegisteredTerrain.MovableTerrain)
//					((RegisteredTerrain.MovableTerrain)p).setMotionAxis(motionAxis);
//				if(depth != null && p instanceof Placeable2D.DepthPlaceable2D)
//					((Placeable2D.DepthPlaceable2D)p).setDepth(depth);
//				if(pos != null)
//					p.getPosition().set(pos);
//				if(p instanceof Scaleable && xScale != null && yScale != null && zScale != null)
//					((Scaleable) p).setScale(xScale, yScale, zScale);
//				if(p instanceof FixedRotateable && rotation != null)
//					((FixedRotateable) p).setRotation(rotation);
//				if(p instanceof FreeRotateable && x != null && y != null && z != null)
//					{
//					((FreeRotateable) p).getXVector().set(x);
//					((FreeRotateable) p).getYVector().set(y);
//					((FreeRotateable) p).getZVector().set(z);
//					}
//				p.transformationChanged(mask);
//				if(p == w.getPivotObject())
//					w.pivotParametersChanged(mask);
//				}
//			
//			protected boolean getGenerateUniqueName()
//				{
//				return makeNameUnique;
//				}
//			}
//		private TransformationData[] transformations;
//		private byte mask;
//		
//		public Transformation(Integer[] selected, Placeable2D[] objects, byte mask)
//			{
//			this.mask = mask;
//			transformations = new TransformationData[selected.length];
//			for(int i = 0; i<selected.length; i++)
//				transformations[i] = new TransformationData(selected[i], objects[i], mask, false);
//			}
//		@Override
//		public void apply(Editor2D w) throws OperationFailedException
//			{
//			for(TransformationData t : transformations)
//				t.apply(w);
//			}
//		public byte getMask()
//			{
//			return mask;
//			}
//		public TransformationData getTransformationData(int indexInSelectedList)
//			{
//			return transformations[indexInSelectedList];
//			}
//		}